#include "vObject.h"
#include "CelSphere.h"

double vObject::SunSize = 0.0;
VECTOR3 vObject::pSun;
Sun_spec vObject::def_SunLight;

vObject::vObject( OBJHANDLE _obj, Scene * scene ) 
	:m_scene(scene)
{
	obj = _obj;

	obj_type = oapiGetObjectType( obj );
	D3DXMatrixIdentity( &mWorld );
	D3DXMatrixIdentity( &mWorld_new );
	oapiGetObjectName( obj, name, 64 );
	rad = oapiGetSize( obj );

	oapiWriteLogV("Loading %s...", name);
}

vObject::~vObject() {
}

//================================================
//			Update
//================================================

void vObject::SaveData() {
	VECTOR3 cpos, gp;
	cpos = GetScene()->GetCamPos();
	//oapiCameraGlobalPos( &cpos );
	
	oapiGetGlobalPos( obj, &GPos_new );
	CPos_new = GPos_new - cpos;
	CDist_new = length( CPos_new );

	double alt = max( 1.0, CDist_new - rad );
	apprad = rad*cfg->cHeight*0.5/(alt*tan( SC->GetCamAperture() ));

	active = apprad > 2.5 ? true : false;//discard inactive objects as soon as possible
	if( !active ) {
		GPos = GPos_new;
		CPos = CPos_new;
		CDist = CDist_new;
		return;
	}

	VECTOR3 tmp = GPos_new;
	normalise( tmp );
	SunDir_new.x = (float)tmp.x;
	SunDir_new.y = (float)tmp.y;
	SunDir_new.z = (float)tmp.z;
	SunDir_new.w = 1.0f;

	oapiGetRotationMatrix( obj, &mROT_new );
	ConstructWorldMatrix( &mWorld_new, &mROT_new, &CPos_new );
}

void vObject::Update() {

	mROT = mROT_new;
	CPos = CPos_new;
	GPos = GPos_new;
	CDist = CDist_new;
	SunDir = SunDir_new;
	mWorld = mWorld_new;
//	ConstructWorldMatrix( &mWorld, &mROT, &CPos );

	CheckResolution();
}

void vObject::ConstructWorldMatrix( D3DXMATRIX *out, MATRIX3 *rot, VECTOR3 *pos ) {
	out->_11 = (float)rot->m11;	out->_12 = (float)rot->m21;	out->_13 = (float)rot->m31;
	out->_21 = (float)rot->m12;	out->_22 = (float)rot->m22;	out->_23 = (float)rot->m32;
	out->_31 = (float)rot->m13;	out->_32 = (float)rot->m23;	out->_33 = (float)rot->m33;
	out->_41 = (float)pos->x;	out->_42 = (float)pos->y;	out->_43 = (float)pos->z;
}

//================================================
//			Vessel and planet distant dots
//================================================

void vObject::InitRenderDot() {
	const UINT CVertexStride = 20, VBOffset = 0;

	iCtx->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );
	iCtx->IASetInputLayout( vStar::IL_BBVertex );
	iCtx->IASetVertexBuffers( 0, 1, &vStar::VB, &CVertexStride, &VBOffset );
	iCtx->VSSetShader( vStar::VS, NULL, NULL );
	iCtx->PSSetShader( vStar::PS, NULL, NULL );
	iCtx->VSSetConstantBuffers( 0, 1, &cb_D3DXMATRIX_x1 );
	iCtx->PSSetConstantBuffers( 0, 1, &cb_D3DXVECTOR4 );
	iCtx->PSSetShaderResources( 0, 1, vVessel::Ball[0]->GetSRV() );
	iCtx->OMSetBlendState( BS_SrcAlpha, D3DXVECTOR4( 1, 1, 1, 1 ), 0xFFFFFFFF );
	iCtx->OMSetDepthStencilState( DSS_NoDepth_NoStencil, 0 );
}

void vObject::RenderDot() {

	double alt = max( 1.0, CDist - rad );
	double apr = rad*cfg->cHeight*0.5/(alt * tan( SC->GetCamAperture() ));
	double ds = 10000.0/CDist;
	double s = 2.0;
	if( apr < 0.3 )	s = 1.0;
	float size = float( rad*ds*s/apr );

	D3DXMATRIX W;
	D3DXVECTOR3
		vCam,
		vPos = D3DXVECTOR3( (float)CPos.x, (float)CPos.y, (float)CPos.z );
	vPos *= (float)ds;

	D3DXVec3Normalize( &vCam, &vPos );
	D3DMAT_CreateX_Billboard( &vCam, &vPos, size, &W );
	W *= *SC->GetVP();
	iCtx->UpdateSubresource( cb_D3DXMATRIX_x1, 0, NULL, &W, 0, 0 );

	float intensity = float( sqrt( 1.0 + dotp( unit( GPos - pSun ), unit( CPos ) )));
	if( intensity > 1.0f )	intensity = 1.0f;
	D3DXCOLOR color( intensity, intensity, intensity, 1.0f );
	iCtx->UpdateSubresource( cb_D3DXVECTOR4, 0, NULL, &color, 0, 0 );

	iCtx->Draw( 4, 0 );
}